% learns given connectome (given as a parameter obj) for recognise given
% input (given as currentInput). This funcion repeats the learnign
% algorithms many times (number of repeatitions is given as epoch parameter)

function obj = learningProcess( obj, currentInput, epoch, firstMemory )    
                                              
       % compute spikes of the connectome
       [output, matrixOfSpikes, usedInput] = computeSpikesMatrix(obj, currentInput ); 
       decreaseSynapsesRemainingTime(obj);
        
        
        %% Probability Algorithm
        %
        
        for learnedLayer=0:obj.numberOfLayers
        
            synapsesToHit = 0;

            % Creates a temporary matrix with the synapses that are in the
            % lottery for having their weight increased or decreased        
            
            
            if (exist('teachingSynapses','var'))
                clearvars teachingSynapses;
            end
            
            if learnedLayer == 0
                for inNeuron=1:obj.inputSize
                    if matrixOfSpikes(inNeuron,1)
                
                        for outNeuron=1:obj.neuronInLayerVector(learnedLayer+1)                    
                            synapse = getSynapse(obj,inNeuron,learnedLayer,outNeuron,learnedLayer+1);
                            %if (synapse.active == 1)
                                synapseID = getSynapseID(obj,inNeuron,learnedLayer,outNeuron,learnedLayer+1);                          
                                teachingSynapses(synapsesToHit+1,:) = [synapseID inNeuron learnedLayer outNeuron learnedLayer+1 synapse.weight];
                                synapsesToHit = synapsesToHit + 1;                        
                            %end
                        end
                    end 
                end
            elseif learnedLayer ~= obj.numberOfLayers
                for inNeuron=1:obj.neuronInLayerVector(learnedLayer)
                    if any(lastNeuronSpiked == inNeuron)
                
                        for outNeuron=1:obj.neuronInLayerVector(learnedLayer+1)                    
                            synapse = getSynapse(obj,inNeuron,learnedLayer,outNeuron,learnedLayer+1);
                            %if (synapse.active == 1)
                                synapseID = getSynapseID(obj,inNeuron,learnedLayer,outNeuron,learnedLayer+1);
                                teachingSynapses(synapsesToHit+1,:) = [synapseID inNeuron learnedLayer outNeuron learnedLayer+1 synapse.weight];
                                synapsesToHit = synapsesToHit + 1;                        
                            %end
                        end
                    end
                end
            else
                for inNeuron=1:obj.neuronInLayerVector(learnedLayer)
                    if any(lastNeuronSpiked == inNeuron)
                
                        for outNeuron=1:obj.outputSize                    
                            synapse = getSynapse(obj,inNeuron,learnedLayer,outNeuron,learnedLayer+1);
                            %if (synapse.active == 1)
                                synapseID = getSynapseID(obj,inNeuron,learnedLayer,outNeuron,learnedLayer+1);
                                teachingSynapses(synapsesToHit+1,:) = [synapseID inNeuron learnedLayer outNeuron learnedLayer+1 synapse.weight];
                                synapsesToHit = synapsesToHit + 1;                        
                            %end
                        end
                    end
                end
            end


            
            
          % Creates an array with an associate probability for all the 
          % synapses in the loterry.
          
          if (exist('teachingSynapses','var'))
            total = sum(teachingSynapses(:,6));

            synapseProb = zeros(synapsesToHit,1);
                
            for count=1:synapsesToHit
                  synapseProb(count) = teachingSynapses(count,6) / total;
            end
        
            selectedSynapse = rand(1);
          
            total = 0;
          
            % Selects the winner for the increasing of weight
            for count=1:synapsesToHit                    
                  total = total + synapseProb(count);
                if selectedSynapse < total                
                     increaseSynapseIndex = count;
                    break;
                end
            end
        
          
            % Increments and decrements the corresponding synapses' weights
            synapseID = teachingSynapses(increaseSynapseIndex,1);
            lastNeuronSpiked = teachingSynapses(increaseSynapseIndex,4);
        
            %if(obj.synapses(synapseID).remainingTime == 0)
                obj.synapses(synapseID).weight = 1+obj.synapses(synapseID).weight;
                obj.synapses(synapseID).remainingTime = obj.synapses(synapseID).definedRechargingTime;
            %end
            
            obj.synapses(synapseID).epochsWithoutUse = 0;
            
            for count=1:length(obj.synapses)
                if count ~= synapseID
                    obj.synapses(count).epochsWithoutUse = obj.synapses(count).epochsWithoutUse + 1;
                end
            end
          end
          
          % Checks which synapses should be fixed as memory and
          % those that should be deleted
          
        

          % Collects data regarding the random number generated by matlab.
          % This array is used by randomNumberInsidence function which
          % plots the number of incidences of all random generated numbers.  
          randomStatistic(epoch,1) = selectedSynapse;
        
          clearvars synapsesToHit;
        end
        
   end
   


